

type StrType<T extends string="str"> = T

let str:StrType = 'str'
let aaa:StrType<'aaa'> = 'aaa'


interface fun<T extends StrType<'bbb'>>{
  name:T
}

let t: fun<'bbb'> = {
  name:'bbb'
}

type VueReact = 'vue' | 'react'
type MappedVR = {[k in VueReact]: k}

type VRKey = keyof MappedVR; // "vue" | "react"

interface Student {
  name: string;
  age: number;
}

type studentKey = keyof Student; // "name" | "age"

type framework = ['vue', 'react', 'angular'];

type frameworkVal1 = framework[number]; // "vue" | "react" | "angular"
type frameworkVal2 = framework[any]; // "vue" | "react" | "angular"

/**
 * 把某一组类型批量映射成另一种类型
 * 这里的 placeholder 可以键入任何你所希望映射成为的类型 
 */
type UnionTypesMap<T> = T extends any ? 'placeholder' : never;

let unionTypesMap:UnionTypesMap<'aa'> = 'placeholder'

//把 联合类型(Union Types) 的每一项映射成某个函数的 返回值。
type UnionTypesMap2Func<T> = T extends any ? () => T : never;

let a:UnionTypesMap2Func<studentKey> = ()=>'name'
let b:UnionTypesMap2Func<studentKey> = ()=>'age'

function combineTupleTypeWithTecursion(T: object[], E: object = {}): object {
  return T.length ? combineTupleTypeWithTecursion(T.slice(1), { ...E, ...T[0] }) : E
}


const ALL_SUITS = ['hearts', 'diamonds', 'spades', 'clubs'] as const; // TS 3.4

type SuitTuple = typeof ALL_SUITS; // readonly ['hearts', 'diamonds', 'spades', 'clubs']

type Suit = SuitTuple[number];  // union type


export type Lit = string | number | boolean | undefined | null | void | {};

export const tuple = <T extends Lit[]>(...args: T) => args;


const ALL_SUITS2 = tuple('hearts', 'diamonds', 'spades', 'clubs', 12,true, undefined, null,'aaa');

type SuitTuple2 = typeof ALL_SUITS2;

type Suit2 = SuitTuple2[number];  // union type


const ALL_SUITS3 = tuple('hearts', 'diamonds', 'spades', 'clubs');

type SuitTuple3 = typeof ALL_SUITS3;

type Suit3 = SuitTuple3[number];  // union type

type StringKey<Base> = Pick<Base,{
  [Key in keyof Base]:Base[Key] extends string? Key : never
}[keyof Base]>

interface Post{
  id:number
  title:string
  description:string
  tags:{id:number},
  createdAt:Date
}
type D = StringKey<Post>  // D = {title:string, description:string}